﻿using S7.Net;
using S7.Net.Types;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using ZR.DataCollection2.Core;
using ZR.Model.Models.ProductionControl;

namespace ImportPlcPointPosition.PLC
{
    /// <summary>
    /// Plc客户端操作类
    /// </summary>
    public class PlcClient
    {




        string IP;
       public Plc plcSession;
        public PlcClient(string iP)
        {
            IP = iP;
            plcSession = new Plc(CpuType.S71500,IP,0,1);
            plcSession.ReadTimeout = 800;
            Debug.WriteLine("plc对象初始化");

        }

        public SieminDecoder Decoder { get; set; }

        public bool Connect()
        {
            try
            {
                if (plcSession.IsConnected)
                    return true;
                plcSession.Open();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool Close()
        {
            try
            {
                if (!plcSession.IsConnected)
                    return true;
                plcSession.Close();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }


        internal string GetStringValue(CksPlcDataPosition one)
        {
            try
            {
                if (!plcSession.IsConnected)
                    return "未连接PLC";
                object result = null;
                switch (one.ParseType)
                {
                    case "int16":    //
                        result = (UInt16)plcSession.Read(one.Address);
                        break;
                    default:
                        if (one.ParseType.StartsWith("string["))
                        {
                            string patternString = @"\DB(\d+).DBB(\d+)\.(\d+)";
                            Match matchString = Regex.Match(one.Address, patternString);
                            if (matchString.Success)
                            {
                                int dbid = int.Parse(matchString.Groups[1].Value);
                                int numberString = int.Parse(matchString.Groups[2].Value);
                                int lengthString = int.Parse(matchString.Groups[3].Value);
                                byte[] buffer = plcSession.ReadBytes(DataType.DataBlock, dbid, numberString, lengthString);
                                result = GetPlcDataString(buffer);
                            }
                        }

                        break;
                }
                if (result == null)
                    return "读取异常";
                return result.ToString();
            }
            catch (Exception ex)
            {
                return "读取异常";
            }
        }

        public string SetValue(CksPlcDataPosition one,string Value)
        {
            try
            {
                if (!plcSession.IsConnected)
                    return "未连接PLC";
                 string pt = one.ParseType;
                if (pt.Contains("["))
                    pt = pt.Substring(0, pt.IndexOf("["));

                switch (pt)
                {
                    case "int":
                    case "int16":    //
                        plcSession.Write(one.Address, Convert.ToInt16(Value));
                        break;
                    case "word": // ushort
                        plcSession.Write(one.Address, Convert.ToUInt16(Value));
                        break;
                    case "string":
                        WriteString(one.BlockDb, (int)one.BytePosition, Value, one.ByteLength);
                        break;
                    case "float":
                    case "real":
                        plcSession.Write(one.Address, Convert.ToSingle(Value));
                        break;
                    case "byte":
                   
                        plcSession.Write(one.Address, Convert.ToByte(Value) );
                        break;
                    case "char":
                        plcSession.Write(one.Address, Encoding.ASCII.GetBytes(Value)[0] );
                        break;
                    case "bool":
                        plcSession.Write(one.Address, Convert.ToBoolean(Value) );
                        break;
                   
                       
                    case "dtl":
                       
                        plcSession.WriteBytes(DataType.DataBlock, one.BlockDb, 
                            (int)one.BytePosition,
                            DateTimeLong.ToByteArray(Convert.ToDateTime(Value)));
                        break;
                    case "dt":
                        plcSession.WriteBytes(DataType.DataBlock, one.BlockDb,
                            (int)one.BytePosition,
                            S7.Net.Types.DateTime.ToByteArray(Convert.ToDateTime(Value)));
                        break;
                    default:
                        throw new Exception("未实现");
                }

                return Value;
            }
            catch (Exception ex)
            {
                throw new Exception("写入异常:"+ex.Message);
                
            }

        }
        public void WriteString(int db,int start ,string value,int lenth)
        {
            // 编码为字节数组
            byte[] stringBytes = Encoding.ASCII.GetBytes(value);
            // 构建带控制信息的字节数组
            byte[] dataString = new byte[lenth]; // 加2是为了存储控制信息
                                                                  // 添加控制信息
            dataString[0] = (byte)(lenth- 2); //第一个字节是字符串的字节总数
            dataString[1] = (byte)(stringBytes.Length); // 第二个字节表示实际使用字节数量
                                                        // 复制字符串数据到字节数组
            Array.Copy(stringBytes, 0, dataString, 2, stringBytes.Length);
            // 将字节数组写入PLC
            plcSession.WriteBytes(S7.Net.DataType.DataBlock, db, start, dataString);

            
        }
        /// <summary>
        /// 将接收的字节处理转换为string字节输出
        /// </summary>
        /// <param name="dataByte"></param>
        /// <returns></returns>
        public string GetPlcDataString(byte[] dataByte)
        {
            try
            {
                int length = Convert.ToInt32(dataByte[1]);//实际使用字节
                if (length > 0)
                {
                    string result = string.Empty;
                    byte[] buffer = new byte[length];
                    for (int i = 0; i < length; i++)
                    {
                        buffer[i] = dataByte[i+2]; //从第3字节是内容 所以需要偏移2
                    }
                    result = Encoding.ASCII.GetString(buffer);
                    return result;
                }
                return "";
            }
            catch
            {

                throw;
            }

        }

       
    }
}
